import 'package:flutter/material.dart';

/// 尽可能的兼容解析，字符串、int和double间的兼容。其他类型不一致不会只会给对应字段赋值为null。debug模式抛异常
/// 转换数据
/// @param json 网络请求回的数据
/// @param key 解析的字段名称
/// @param type 可选参数，定义字段数据类型，注：该参数必须与对象中[key]的类型一致
/// 如果是List<>类型，type生成的是List<dynamic>而不是具体泛型
dynamic safeParse(Map<String, dynamic> json, String key, [String type]) {
  var value = json[key];
  if (value == null) return null;

  // runtime是List，但定义的类型不是List则返回null
  if (value is List && type?.startsWith('List') != true) {
    return null;
  }

  if (type == null) return value;
  // 定义的是List
  if (type.startsWith('List')) {
    if (value is List) {
      if (type == 'List' || type == 'List<dynamic>') {
        return value;
      }

      // 泛型是基本类型
      return value.map((f) {
        return _parse(key, type.substring(/*'List<'.length*/ 5, type.length - 1), f);
      }).toList();
    } else {
      // 定义的是List，但返回的不是，则直接return null
      return null;
    }
  }

  // List
//  if (type.startsWith('List') && value is List) {
//    if (type == 'List' || type == 'List<dynamic>') {
//      return value;
//    }
//
//    return value.map((f) {
//      return _parse(key, type.substring(/*'List<'.length*/ 5, type.length - 1), f);
//    }).toList();
//  }

  String runtimeType = value.runtimeType.toString();
  if (type == runtimeType ||
      (type.startsWith('List') && value is List) ||
      (type.startsWith('Map') && value is Map)) {
    return value;
  }

  debugPrint('safeParse:{key=$key,value=$value,defineType=$type,runTimeType=$runtimeType}');
  return _parse(key, type, value);
}

_parse(String key, String type, dynamic value) {
  // 客户端声明的类型
  switch (type) {
    case 'String':
      if (value is num) {
        return value.toString();
      }
      break;
    case 'num':
      if (value is num) {
        return value;
      }
      if (value is String) {
        return num.tryParse(value);
      }
      break;
    case 'int':
      if (value is num) {
        return value.toInt();
      }
      if (value is String) {
        return num.tryParse(value)?.toInt();
      }
      break;
    case 'double':
      if (value is num) {
        return value.toDouble();
      }
      if (value is String) {
        return num.tryParse(value)?.toDouble();
      }
      break;
  }

  debugPrint('safeParse:{key=$key, defineType=$type, value=$value}');
  return null;
}
